/*
 *  +----------------------------------------------------------------------
 *  | sophon [ A FAST GAME FRAMEWORK ]
 *  +----------------------------------------------------------------------
 *  | Copyright (c) 2023-2029 All rights reserved.
 *  +----------------------------------------------------------------------
 *  | Licensed ( http:www.apache.org/licenses/LICENSE-2.0 )
 *  +----------------------------------------------------------------------
 *  | Author: jqiris <1920624985@qq.com>
 *  +----------------------------------------------------------------------
 */

use anyhow::anyhow;
use anyhow::Result;
use prost::Message;
use serde::{de::DeserializeOwned, Serialize};

use crate::{logger::*, utils::*};
use crate::error;

use super::*;

const MSG_HEAD_LENGTH: usize = 0x08;

#[derive(Debug)]
pub enum MessageType {
    MsgTypeRequest = 0x00,
    MsgTypePublish = 0x01,
    MsgTypeResponse = 0x02,
}

impl From<&u8> for MessageType {
    fn from(v: &u8) -> Self {
        match *v {
            0x00 => MessageType::MsgTypeRequest,
            0x01 => MessageType::MsgTypePublish,
            0x02 => MessageType::MsgTypeResponse,
            _ => MessageType::MsgTypeRequest,
        }
    }
}

#[derive(Debug)]
pub struct MsgRpc<T: Default> {
    pub msg_type: MessageType,
    pub msg_id: i32,
    pub msg_data: Option<T>,
}

impl<T: Default> MsgRpc<T> {
    pub fn new(msg_type: MessageType, msg_id: i32, msg_data: Option<T>) -> Self {
        Self {
            msg_type,
            msg_id,
            msg_data,
        }
    }
}

impl<T: Default> Default for MsgRpc<T> {
    fn default() -> Self {
        Self {
            msg_type: MessageType::MsgTypeRequest,
            msg_id: 0,
            msg_data: Some(T::default()),
        }
    }
}

pub struct Encoder {
    proto_encoder: ProtoSerializer,
    json_encoder: JsonSerializer,
}

impl Encoder {
    pub fn new() -> Self {
        Self {
            proto_encoder: ProtoSerializer::new(),
            json_encoder: JsonSerializer::new(),
        }
    }
}

impl Encoder {
    fn encode_next(
        &self,
        msg_type: MessageType,
        msg_id: i32,
        data: &mut Vec<u8>,
    ) -> Result<Vec<u8>> {
        let length = MSG_HEAD_LENGTH + data.len();
        let mut buf = Vec::<u8>::with_capacity(MSG_HEAD_LENGTH);
        buf.push(((length >> 16) & 0xFF) as u8);
        buf.push(((length >> 8) & 0xFF) as u8);
        buf.push((length & 0xFF) as u8);
        buf.push(msg_type as u8);
        buf.push(((msg_id >> 24) & 0xFF) as u8);
        buf.push(((msg_id >> 16) & 0xFF) as u8);
        buf.push(((msg_id >> 8) & 0xFF) as u8);
        buf.push((msg_id & 0xFF) as u8);
        buf.append(data);
        Ok(buf)
    }
    pub fn encode_proto<T: Message + Default>(&self, msg: MsgRpc<T>) -> Result<Vec<u8>> {
        let mut data = Vec::<u8>::new();
        if let Some(err) = msg.msg_data.as_ref().and_then(|v2| {
            match self.proto_encoder.marshal(v2) {
                Ok(res) => {
                    data = res;
                }
                Err(err) => {
                    return Some(err);
                }
            };
            None
        }) {
            return Err(err);
        }
        self.encode_next(msg.msg_type, msg.msg_id, &mut data)
    }

    pub fn encode_json<T: Serialize + DeserializeOwned + Default>(
        &self,
        msg: MsgRpc<T>,
    ) -> Result<Vec<u8>> {
        let mut data = Vec::<u8>::new();
        if let Some(err) = msg.msg_data.as_ref().and_then(|v2| {
            match self.json_encoder.marshal(v2) {
                Ok(res) => {
                    data = res;
                }
                Err(err) => {
                    return Some(err);
                }
            };
            None
        }) {
            return Err(err);
        }
        self.encode_next(msg.msg_type, msg.msg_id, &mut data)
    }

    fn decode_before(&self, data: Vec<u8>) -> (MessageType, usize, Vec<u8>) {
        let msg_length = big_bytes_to_usize(data.get(0..3).unwrap());
        let msg_type: MessageType = data.get(3).unwrap().into();
        let msg_id = big_bytes_to_usize(data.get(4..8).unwrap());
        let msg_data = data.get(MSG_HEAD_LENGTH..msg_length).unwrap().to_vec();
        (msg_type, msg_id, msg_data)
    }

    pub fn decode_proto<T: Message + Default>(&self, data: Vec<u8>) -> Result<MsgRpc<T>> {
        if data.len() < MSG_HEAD_LENGTH {
            return Err(anyhow!("invalid message length"));
        }
        let (msg_type, msg_id, msg_data) = self.decode_before(data);
        let mut msg = MsgRpc::<T>::default();
        msg.msg_type = msg_type;
        msg.msg_id = msg_id as i32;
        match self.proto_encoder.unmarshal(msg_data) {
            Ok(v) => {
                msg.msg_data = Some(v);
                Ok(msg)
            }
            Err(err) => Err(err),
        }
    }

    pub fn decode_json<T: Serialize + DeserializeOwned + Default>(
        &self,
        data: Vec<u8>,
    ) -> Result<MsgRpc<T>> {
        if data.len() < MSG_HEAD_LENGTH {
            return Err(anyhow!("invalid message length"));
        }
        let (msg_type, msg_id, msg_data) = self.decode_before(data);
        let mut msg = MsgRpc::<T>::default();
        msg.msg_type = msg_type;
        msg.msg_id = msg_id as i32;
        match self.json_encoder.unmarshal(msg_data) {
            Ok(v) => {
                msg.msg_data = Some(v);
                Ok(msg)
            }
            Err(err) => Err(err),
        }
    }

    pub fn decode_header(&self, data: Vec<u8>) -> Result<MsgRpc<Vec<u8>>> {
        if data.len() < MSG_HEAD_LENGTH {
            return Err(anyhow!("invalid message length"));
        }
        let (msg_type, msg_id, msg_data) = self.decode_before(data);
        let mut msg = MsgRpc::<Vec<u8>>::default();
        msg.msg_type = msg_type;
        msg.msg_id = msg_id as i32;
        if msg_data.len() > 0 {
            msg.msg_data = Some(msg_data);
        } else {
            msg.msg_data = None;
        }
        Ok(msg)
    }

    pub fn encode_proto_msg<T: Message + Default>(&self, msg: Option<T>) -> Result<Vec<u8>> {
        let mut data = Vec::<u8>::new();
        if let Some(err) = msg.as_ref().and_then(|v2| {
            match self.proto_encoder.marshal(v2) {
                Ok(res) => {
                    data = res;
                }
                Err(err) => {
                    return Some(err);
                }
            };
            None
        }) {
            return Err(err);
        }
        Ok(data)
    }

    pub fn encode_json_msg<T: Serialize + DeserializeOwned>(
        &self,
        msg: Option<T>,
    ) -> Result<Vec<u8>> {
        let mut data = Vec::<u8>::new();
        if let Some(err) = msg.as_ref().and_then(|v2| {
            match self.json_encoder.marshal(v2) {
                Ok(res) => {
                    data = res;
                }
                Err(err) => {
                    return Some(err);
                }
            };
            None
        }) {
            return Err(err);
        }
        Ok(data)
    }

    pub fn decode_proto_msg<T: Message + Default>(&self, data: Vec<u8>) -> Result<T> {
        match self.proto_encoder.unmarshal(data) {
            Ok(v) => Ok(v),
            Err(err) => Err(err),
        }
    }

    pub fn decode_json_msg<T: Serialize + DeserializeOwned>(&self, data: Vec<u8>) -> Result<T> {
        match self.json_encoder.unmarshal(data) {
            Ok(v) => Ok(v),
            Err(err) => Err(err),
        }
    }

    pub fn reponse_proto<T: Message + Default>(&self, data: Option<T>) -> Option<Vec<u8>> {
        let msg = MsgRpc::new(MessageType::MsgTypeResponse, 0 as i32, data);
        match self.encode_proto::<T>(msg) {
            Ok(v) => Some(v),
            Err(err) => {
                error!("reponse err:{}", err);
                None
            }
        }
    }

    pub fn reponse_json<T: Serialize + DeserializeOwned + Default>(
        &self,
        data: Option<T>,
    ) -> Option<Vec<u8>> {
        let msg = MsgRpc::new(MessageType::MsgTypeResponse, 0 as i32, data);
        match self.encode_json::<T>(msg) {
            Ok(v) => Some(v),
            Err(err) => {
                error!("reponse err:{}", err);
                None
            }
        }
    }
}

unsafe impl Send for Encoder {}

unsafe impl Sync for Encoder {}

#[cfg(test)]
mod configs {
    use crate::treaty::*;

    use super::*;

    #[test]
    fn test_default_encoder() {
        let encoder = Encoder::new();
        let data = Server {
            server_name: "test_server".into(),
            server_id: "1001".into(),
            ..Default::default()
        };
        let msg = MsgRpc {
            msg_type: MessageType::MsgTypeResponse,
            msg_id: 18 as i32,
            msg_data: Some(data),
        };
        match encoder.encode_proto(msg) {
            Ok(v) => {
                match encoder.decode_proto::<Server>(v) {
                    Ok(msg2) => {
                        println!("msg2:{:?}", msg2);
                        // let data3: ProtoItem<Server> =
                        //     msg2.msg_data.unwrap().read().unwrap().into();
                    }
                    Err(err) => eprint!("err:{}", err),
                }
            }
            Err(err) => eprintln!("err:{}", err),
        };
    }
}
